<?php

namespace App\Http\Middleware;

use App\Facades\ScarecrowAuth;
use App\Models\AuthManage\LoginModel;
use Closure;
use Illuminate\Support\Facades\Crypt;

/**
 * 用户鉴权中间件
 * Class ApiTokenCheckMiddleware
 * @package App\Http\Middleware
 */
class ApiTokenCheckMiddleware
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
		$tokenStr = $request->header('SC-API-TOKEN');
		if (!$request->header('SC-API-TOKEN')) {
			$tokenStr = $request->input('SC-API-TOKEN', "");
			if (!$tokenStr || $tokenStr=='null') {
				$this->returnError();
			}
		}

		try {
			$token = Crypt::decryptString($tokenStr);
			$userObj = ScarecrowAuth::user($token);
			if (!$userObj) {
				$this->returnError('用户尚未登录');
			}

			//如果是超级管理员则不检测权限
			if ($userObj['is_supper_admin'] != 1) {
				//检查用户权限
				$authList = $userObj['authList'] ?: [];
				if (!$this->CheckAuthList($authList)) {
					$this->returnError('无权限访问此接口', API_SUCCESS);
				}
			}

			//更新TOKEN访问信息
			$info = $this->updateTokenInfo($token, $userObj['tokenInfo']);
			if ($info['code'] !== 0) {
				$this->returnError('TOKEN失效，请重新登录', API_CHECK_TOKEN_FAIL);
			}

			defined('APP_USER_TOKEN') OR define('APP_USER_TOKEN', $token);
			return $next($request);
		} catch (\Throwable $e) {
			if (config('app.debug')) {
				$this->returnError($e->getMessage());
			} else {
				$this->returnError();
			}
		}
    }

	/**
	 * 检查权限列表
	 * @param array $authList
	 * @return bool
	 */
    public function CheckAuthList($authList = []) {
    	//在此处填写权限判定逻辑
		$nowRoute = strtolower(request()->path());
		$nowRoute = trim($nowRoute, '/');
		if (in_array($nowRoute, $authList ? : [])) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * 更新用户TOKEN信息
	 * @param array $tokenInfo
	 * @return bool
	 */
	public function updateTokenInfo($token, $tokenInfo = []) {
		if ($tokenInfo['is_invalid'] == 1 || $tokenInfo['expire_time'] < time() || $tokenInfo['call_num'] < 1) {
			LoginModel::LoginOut($token);
			$this->returnError(0, 'TOKEN已失效，请重新登录');
		}

		$tokenInfo['call_num'] = $tokenInfo['call_num'] - 1;
		$updateCacheData = [
			'call_num'  =>  $tokenInfo['call_num'],
			'update_time'	=>	time()
		];
		return LoginModel::updateTokenCache($token, $updateCacheData, $tokenInfo['call_num'] % 10 === 0);
	}

	/**
	 * 返回错误信息
	 * @param string $str
	 */
    protected function returnError($str = 'TOKEN错误', $code = API_CHECK_TOKEN_FAIL) {
		die(ApiReturn('NO', $str, [], $code));
	}
}
